package com.linkhub.oms.admin.common.exception;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.text.StrPool;
import com.linkhub.oms.admin.common.enums.SaLoginExTypeEnum;
import com.linkhub.oms.common.enums.ResponseCodeEnum;
import com.linkhub.oms.common.exception.BizException;
import com.linkhub.oms.common.response.DataResponse;
import com.linkhub.oms.common.util.json.QtFastjsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Description: GlobalExceptionHandler
 * @Author: echo
 * @Date: 2024/3/2 22:23
 * @Version: 1.0
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler({BizException.class})
    public DataResponse<String> handleBizException(BizException ex) {
        log.error("GlobalExceptionHandler BizException: ", ex);
        String data = Objects.nonNull(ex.getData()) ? QtFastjsonUtil.toJSONString(ex.getData()) : null;
        return DataResponse.fail(String.valueOf(ex.getErrCode()), ex.getMessage(), data);
    }


    @ExceptionHandler({MethodArgumentNotValidException.class, ConstraintViolationException.class, BindException.class})
    public DataResponse<String> handleMethodArgumentNotValidException(Exception ex) {
        List<String> errorList = new ArrayList<>();
        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException methodException = (MethodArgumentNotValidException) ex;
            methodException.getBindingResult().getFieldErrors().forEach(error -> errorList.add(error.getDefaultMessage()));
        } else if (ex instanceof ConstraintViolationException) {
            ConstraintViolationException constraintException = (ConstraintViolationException) ex;
            constraintException.getConstraintViolations().forEach(error -> errorList.add(error.getMessage()));
        } else if (ex instanceof BindException) {
            BindException bindException = (BindException) ex;
            bindException.getBindingResult().getFieldErrors().forEach(error -> errorList.add(error.getDefaultMessage()));
        }
        log.error("GlobalExceptionHandler handleMethodArgumentNotValidException:{}", QtFastjsonUtil.toJSONString(errorList));
        return DataResponse.fail(ResponseCodeEnum.PARAMS_ERROR, StringUtils.join(errorList, StrPool.C_COMMA));
    }

    @ExceptionHandler({NotLoginException.class})
    public DataResponse<String> handleNotLoginException(NotLoginException nte) {
        log.error("GlobalExceptionHandler handleNotLoginException: ", nte);
        String token = StpUtil.getTokenValue();
        if (StringUtils.isNotBlank(token)) {
            StpUtil.getStpLogic().deleteTokenToIdMapping(token);
        }
        return DataResponse.fail(SaLoginExTypeEnum.convertResponseCode(nte.getType()));
    }

    @ExceptionHandler({NotRoleException.class})
    public DataResponse<String> handleNotRoleException(NotRoleException ex) {
        log.error("GlobalExceptionHandler handleNotRoleException: ", ex);
        return DataResponse.fail(ResponseCodeEnum.AUTH_ERROR);
    }

    @ExceptionHandler({Exception.class})
    public DataResponse<String> handleException(Exception ex) {
        log.error("GlobalExceptionHandler handleException: ", ex);
        return DataResponse.fail(ResponseCodeEnum.SYS_ERROR);
    }
}
